const fs = require('fs');

/**
 * 用nodejs生成压缩代码包
 * -----------------------
 */
class Tool {
  constructor() {
    this.randBuildVer = false; // 打包时是否使用当前时间做版本号，避免测试环境重复装包冲突
  }

  getNowTime() {
    const now = new Date();
    const year = now.getFullYear();
    const month = now.getMonth() + 1;
    const day = now.getDate();
    return `${year}年${month}月${day}日`;
  }

  async getNewVersion() {
    const now = new Date();
    const year = now.getFullYear();
    const month = now.getMonth() + 1;
    const day = now.getDate();
    let hh = now.getHours();
    let mm = now.getMinutes();

    if (hh < 10) {
      hh = `0${hh}`;
    }
    if (mm < 10) {
      mm = `0${mm}`;
    }

    const detailVersion = `${year}-${month}-${day}_${hh}${mm}`;

    const metaFile = './AssetPack/vapp-meta-data.json';
    const obj = require(metaFile);
    let mainVersion = obj.version;

    if (this.randBuildVer) {
      mainVersion = detailVersion;
    }

    const version = {
      main: mainVersion,
      detail: detailVersion,
    };

    return version;
  }

  async buildZip() {
    const metaFile = './AssetPack/vapp-meta-data.json';
    const oldCode = fs.readFileSync(metaFile).toString();
    const obj = require(metaFile);

    // --------- 修改 AssetPack/vapp-meta-data.json
    const version = await this.getNewVersion();
    obj.version = version.main;
    obj.generationDate = this.getNowTime();

    const json = JSON.stringify(obj, null, 2);
    fs.writeFileSync(metaFile, json);

    // --------- 压缩并还原文件代码
    const zipName = `${obj.xvueNameSpace}_${obj.version}`;
    await this.zip('./AssetPack/', `${zipName}.zip`);

    this.modifySignYml(zipName);
    fs.writeFileSync(metaFile, oldCode);
  }

  /**
   * 压缩文件
   * @param  {string} dir     要压缩的文件目录，如： “d:/www/hello/”
   * @param  {string} zipFile 压缩文件输出到路径，如：“d:/www/abc.zip”
   * @return {[type]}         压缩完的文件不包含外层文件夹，如hello
   */
  zip(dir, zipFile) {
    return new Promise(resolve => {
      if (/\.zip$/.test(zipFile)) {
        const hasFile = fs.existsSync(zipFile);
        if (hasFile) {
          fs.unlink(zipFile, err => {});
        }
        const archiver = require('archiver');
        const output = fs.createWriteStream(zipFile);
        const archive = archiver('zip', {
          zlib: { level: 9 },
        });
        output.on('close', () => {
          resolve(true);
        });
        archive.on('error', err => {
          throw err;
        });
        archive.pipe(output);
        archive.directory(dir, false);
        archive.finalize();
      } else {
        resolve(false);
      }
    })
  }

  async buildZipAfterSign() {
    const outputDir = './OUTPUT';
    if (fs.existsSync(outputDir)) {
      const files = fs.readdirSync(outputDir);
      for (let i = 0; i < files.length; i++) {
        const path = `${outputDir}/${files[i]}`;
        const stats = fs.statSync(path);
        if (stats.isFile()) {
          const fileName = files[i].replace(/^.*\/([^/]+.zip)$/, '$1');
          fs.copyFileSync(path, `./${fileName}`);
        }
      }
    }
    this.modifySignYml('AssetPack');
  }

  modifySignYml(version) {
    const ymlFile = './asset-signature-V1.1/application.yml';
    let code = fs.readFileSync(ymlFile).toString();
    code = code.replace(/input\.file: (.+\.zip)/, `input.file: ${version}.zip`);
    fs.writeFileSync(ymlFile, code);
  }

  // 生成语言包
  async buildLanguageExcel() {
    const xlsx = require('node-xlsx');
    const langFile = './public/i18n/languages_all.js';
    const langArr = require(langFile);

    const langObj = {};
    langArr.forEach(n => {
      const title = ['key', 'value'];
      const { key } = n;
      Object.keys(n || {}).forEach(i=>{
        if (i !== 'key') {
          if (!langObj[i]) {
            langObj[i] = [title];
          }
          langObj[i].push([key, n[i]]);
        }
      });
    });
    langObj['th-TH'] = langObj['zh-CN']; // 泰文使用中文代替

    const sheetData = [];
    Object.keys(langObj || {}).forEach(i=>{
      sheetData.push({
        name: i,
        data: langObj[i],
      });
    });

    // 重复项检查
    const map = {};
    sheetData[0].data.forEach(n => {
      const [key, value] = n;
      if (!map[key]) {
        map[key] = [value];
      } else {
        map[key].push(value);
      }
    });
    const dupItems = Object.entries(map)
      .filter(n => n[1].length > 1)
      .map(([key, value]) => ({ [key]: value }));
    if (dupItems.length > 0) {
      this.showLog('存在重复项，public端导入国际化不允许有重复项，否则会导入失败，请先清除重复项再重试');
      this.showLog(dupItems);
      return;
    }
    const buffer = xlsx.build(sheetData);
    const excelFile = './package/tenant/sc-visual/source/international/RthllVapp_RthllVapp.xlsx';
    fs.writeFileSync(excelFile, buffer, { flag: 'w' });
  }

}

const action = process.argv[2]; // 'zip'
const tool = new Tool();
(async () => {
  // 压缩生成资产包
  if (action === 'zip') {
    await tool.buildZip();
  }

  // 加签完后，后续处理
  if (action === 'after_sign') {
    await tool.buildZipAfterSign();
  }

  // 生成语言包
  if (action === 'lang') {
    await tool.buildLanguageExcel();
  }

})();
